package net.zoneland.zrdp.framework.interceptor.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;

import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import net.zoneland.zrdp.common.annotation.RepeatSubmit;
import net.zoneland.zrdp.common.constant.CacheConstants;
import net.zoneland.zrdp.common.core.redis.RedisService;
import net.zoneland.zrdp.common.filter.RepeatedlyRequestWrapper;
import net.zoneland.zrdp.common.utils.JacksonUtils;
import net.zoneland.zrdp.common.utils.http.HttpHelper;
import net.zoneland.zrdp.framework.interceptor.RepeatSubmitInterceptor;

/**
 * 判断请求url和数据是否和上一次相同，
 * 如果和上次相同，则是重复提交表单。 有效时间为10秒内。
 *
 * @author zonevue
 */
@Component
public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
    // 令牌自定义标识
    @Value("${token.header}")
    private String header;

    @Resource
    private RedisService redisService;


    @Override
    public boolean isRepeatSubmit(final HttpServletRequest request, final RepeatSubmit annotation) throws JsonProcessingException {
        String nowParams = "";
        if (request instanceof RepeatedlyRequestWrapper) {
            final RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
            nowParams = HttpHelper.getBodyString(repeatedlyRequest);
        }

        // body参数为空，获取Parameter的数据
        if (StringUtils.isEmpty(nowParams)) {
            nowParams = JacksonUtils.toJsonString(request.getParameterMap());
        }
        final RepeatEntity nowDataRepeatEntity = new RepeatEntity(nowParams, System.currentTimeMillis());

        // 请求地址（作为存放cache的key值）
        final String url = request.getRequestURI();

        // 唯一值（没有消息头则使用请求地址）
        final String submitKey = StringUtils.trimToEmpty(request.getHeader(header));

        // 唯一标识（指定key + url + 消息头）
        final String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;

        final String sessionObj = redisService.getCacheString(cacheRepeatKey);
        if (sessionObj != null) {
            final Map<String, RepeatEntity> sessionMap = JacksonUtils.toTypeObject(sessionObj, new TypeReference<Map<String, RepeatEntity>>() {});
            if (sessionMap.containsKey(url)) {
                final RepeatEntity preDataMapRepeatEntity = sessionMap.get(url);
                if (compareParams(nowDataRepeatEntity, preDataMapRepeatEntity) &&
                    compareTime(nowDataRepeatEntity, preDataMapRepeatEntity, annotation.interval())) {
                    return true;
                }
            }
        }
        final Map<String, RepeatEntity> cacheMap = new HashMap<>();
        cacheMap.put(url, nowDataRepeatEntity);
        redisService.setCacheString(cacheRepeatKey, JacksonUtils.toJsonString(cacheMap), annotation.interval(), TimeUnit.MILLISECONDS);
        return false;
    }

    /**
     * 判断参数是否相同
     */
    private boolean compareParams(final RepeatEntity nowMap, final RepeatEntity preMap) {
        final String nowParams = nowMap.getRepeatParams();
        final String preParams = preMap.getRepeatParams();
        return nowParams.equals(preParams);
    }

    /**
     * 判断两次间隔时间
     */
    private boolean compareTime(final RepeatEntity nowMap, final RepeatEntity preMap, final int interval) {
        final long time1 = nowMap.getRepeatTime();
        final long time2 = preMap.getRepeatTime();
        return (time1 - time2) < interval;
    }
}

@Data
class RepeatEntity {
    private String repeatParams;

    private long repeatTime;

    public RepeatEntity(final String repeatParams, final long repeatTime){
        this.repeatParams = repeatParams;
        this.repeatTime = repeatTime;
    }
}
